using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using MatrixFramework.Shared.Contracts.Monitoring;

namespace MatrixFramework.Shared.Application.Monitoring
{
    /// <summary>
    /// OpenTelemetry分布式追踪应用服务
    /// 符合ABP vNext规范，提供可重用的监控功能
    /// </summary>
    public class OpenTelemetryAppService : ApplicationService, IOpenTelemetryService, ITransientDependency
    {
        private readonly ILogger<OpenTelemetryAppService> _logger;
        private readonly IOptions<OpenTelemetryOptions> _options;
        private readonly Meter? _meter;
        private readonly Counter<long>? _requestCounter;
        private readonly Counter<long>? _errorCounter;

        public OpenTelemetryAppService(
            ILogger<OpenTelemetryAppService> logger,
            IOptions<OpenTelemetryOptions> options)
        {
            _logger = logger;
            _options = options;

            if (_options.Value.Enabled)
            {
                var serviceName = string.IsNullOrEmpty(_options.Value.Prometheus.MetricsPrefix)
                    ? _options.Value.ServiceName
                    : _options.Value.Prometheus.MetricsPrefix;

                // 创建Meter
                _meter = new Meter(serviceName, _options.Value.ServiceVersion);

                // 请求计数器
                _requestCounter = _meter.CreateCounter<long>($"{serviceName}_requests_total", "Total number of requests");

                // 错误计数器
                _errorCounter = _meter.CreateCounter<long>($"{serviceName}_errors_total", "Total number of errors");
            }
        }

        /// <summary>
        /// 创建追踪活动
        /// </summary>
        public IDisposable StartOperation(string operationName, Dictionary<string, object>? tags = null)
        {
            if (!_options.Value.Tracing.Enabled)
            {
                return new NoOpDisposable();
            }

            var activity = new Activity(_options.Value.ServiceName + "." + operationName).Start();

            if (activity != null && tags != null)
            {
                foreach (var tag in tags)
                {
                    activity.SetTag(tag.Key, tag.Value?.ToString());
                }
            }

            return new ActivityDisposable(activity);
        }

        /// <summary>
        /// 记录指标
        /// </summary>
        public void RecordMetric(string metricName, double value, Dictionary<string, object>? tags = null)
        {
            if (!_options.Value.Enabled)
            {
                return;
            }

            try
            {
                // 使用预定义的计数器
                if (_requestCounter != null)
                {
                    _requestCounter.Add(1, new KeyValuePair<string, object?>("metric_name", metricName));
                }

                _logger.LogDebug("记录指标: {MetricName} = {Value}", metricName, value);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录指标失败: {MetricName}", metricName);
            }
        }

        /// <summary>
        /// 增加计数器
        /// </summary>
        public void IncrementCounter(string counterName, Dictionary<string, object>? tags = null)
        {
            if (!_options.Value.Enabled)
            {
                return;
            }

            try
            {
                if (_requestCounter != null)
                {
                    _requestCounter.Add(1, new KeyValuePair<string, object?>("counter_name", counterName));
                }

                _logger.LogDebug("增加计数器: {CounterName}", counterName);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "增加计数器失败: {CounterName}", counterName);
            }
        }

        /// <summary>
        /// 记录直方图数据
        /// </summary>
        public void RecordHistogram(string histogramName, double value, Dictionary<string, object>? tags = null)
        {
            if (!_options.Value.Enabled)
            {
                return;
            }

            try
            {
                _logger.LogDebug("记录直方图: {HistogramName} = {Value}", histogramName, value);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录直方图失败: {HistogramName}", histogramName);
            }
        }

        /// <summary>
        /// 设置仪表盘值
        /// </summary>
        public void SetGauge(string gaugeName, double value, Dictionary<string, object>? tags = null)
        {
            if (!_options.Value.Enabled)
            {
                return;
            }

            try
            {
                _logger.LogDebug("设置仪表盘: {GaugeName} = {Value}", gaugeName, value);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "设置仪表盘失败: {GaugeName}", gaugeName);
            }
        }

        /// <summary>
        /// 添加事件到当前活动
        /// </summary>
        public void AddEvent(string eventName, Dictionary<string, object>? tags = null)
        {
            try
            {
                var activity = Activity.Current;
                if (activity != null)
                {
                    activity.AddEvent(new ActivityEvent(eventName, tags: ConvertToTags(tags)));
                }

                _logger.LogDebug("添加事件: {EventName}", eventName);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "添加事件失败: {EventName}", eventName);
            }
        }

        /// <summary>
        /// 设置标签到当前活动
        /// </summary>
        public void SetTags(Dictionary<string, object> tags)
        {
            try
            {
                var activity = Activity.Current;
                if (activity != null && tags != null)
                {
                    foreach (var tag in tags)
                    {
                        activity.SetTag(tag.Key, tag.Value?.ToString());
                    }
                }

                _logger.LogDebug("设置标签: {TagCount} 个标签", tags?.Count ?? 0);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "设置标签失败");
            }
        }

        /// <summary>
        /// 记录异常到当前活动
        /// </summary>
        public void RecordException(Exception exception)
        {
            try
            {
                var activity = Activity.Current;
                if (activity != null)
                {
                    activity.SetStatus(ActivityStatusCode.Error, exception.Message);
                    activity.SetTag("exception.type", exception.GetType().Name);
                    activity.SetTag("exception.message", exception.Message);
                }

                _logger.LogError(exception, "记录异常到追踪");
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "记录异常失败");
            }
        }

        /// <summary>
        /// 转换标签字典
        /// </summary>
        private static ActivityTagsCollection? ConvertToTags(Dictionary<string, object>? tags)
        {
            if (tags == null || tags.Count == 0)
                return null;

            var tagCollection = new ActivityTagsCollection();
            foreach (var tag in tags)
            {
                tagCollection.Add(tag.Key, tag.Value?.ToString());
            }
            return tagCollection;
        }

        /// <summary>
        /// 空操作可释放对象
        /// </summary>
        private class NoOpDisposable : IDisposable
        {
            public void Dispose() { }
        }

        /// <summary>
        /// 活动可释放对象
        /// </summary>
        private class ActivityDisposable : IDisposable
        {
            private readonly Activity? _activity;

            public ActivityDisposable(Activity? activity)
            {
                _activity = activity;
            }

            public void Dispose()
            {
                _activity?.Stop();
                _activity?.Dispose();
            }
        }
    }
}